package org.boulderfoodrescue.webapp.client.donors;

import org.boulderfoodrescue.webapp.client.googlemap.GoogleMap;
import org.boulderfoodrescue.webapp.client.managers.LoginInfoManager;
import org.boulderfoodrescue.webapp.client.multipleaddresspanel.MultipleAdressDialog;
import org.boulderfoodrescue.webapp.shared.Location;
import org.boulderfoodrescue.webapp.shared.Location.LocationType;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LocationCallback;
import com.google.gwt.maps.client.geocode.Placemark;
import com.google.gwt.maps.client.geocode.StatusCodes;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class SetLocationInfoView extends Composite implements HasValue<Location>{

	private static SetLocationInfoViewUiBinder uiBinder = GWT
			.create(SetLocationInfoViewUiBinder.class);

	interface SetLocationInfoViewUiBinder extends
	UiBinder<Widget, SetLocationInfoView> {
	}

	public SetLocationInfoView(LocationType type) {
		this.type = type;
		initWidget(uiBinder.createAndBindUi(this));
		locationSpecifics.setVisible(false);
		location = new Location(type);
		switch(type){
		case Donor:
			title.setText("New Donor");
			break;
		case Recipient:
			title.setText("New Recipient");
			break;
		default:
			title.setText("Unkown Location Type");
		}
		searchBox.setFocus(true);
	}
	@UiField
	TextBox contact_name;
	@UiField
	TextBox contact_email;
	@UiField
	TextBox contact_phone;
	@UiField
	Label address_found_text1;
	@UiField
	Label address_found_text2;
	@UiField
	Button button_next;
	@UiField
	Button button_cancel_save;
	@UiField
	TextBox location_name;
	@UiField
	ListBox foodType;
	@UiField
	TextArea pickup_notes;
	@UiField
	GoogleMap googleMap;
	@UiField
	TextBox searchBox;
	@UiField
	Button button_find;
	@UiField
	FlowPanel locationSearch;
	@UiField
	FlowPanel locationSpecifics;
	@UiField
	Label editButton;
	@UiField
	Label title;

	private static final String TextBoxFormatError = "dateBoxFormatError";
	private Location value;
	private Location location;
	private LocationType type;

	public void onAddressFound(Placemark placemark){
		googleMap.removeMarker(location);
		location = new Location(type);
		reset();
		location.setStreetAddress(placemark.getStreet());
		location.setCity(placemark.getCity());
		location.setState(placemark.getState());
		location.setZipCode(placemark.getPostalCode());
		address_found_text1.setText(location.firstLineOfAddress());
		address_found_text2.setText(location.secondLineOfAddress());
		googleMap.addMarker(location, placemark.getPoint(), false);
		location.setLatitude(placemark.getPoint().getLatitude());
		location.setLongitude(placemark.getPoint().getLongitude());

		contact_name.setFocus(true);

		locationSearch.setVisible(false);
		locationSpecifics.setVisible(true);
	}

	@UiHandler("searchBox")
	public void onEnterKeyHit(KeyUpEvent e)
	{
		if (KeyCodes.KEY_ENTER == e.getNativeKeyCode())
			onFindClick(null);
	}

	@UiHandler("editButton")
	public void onEditButtonClicked(ClickEvent e){
		switchMode(true);
		searchBox.setText(location.getLatitude() + " " + location.getLongitude());
	}

	private void switchMode(Boolean findAddress){
		if(findAddress){
			locationSearch.setVisible(true);
			locationSpecifics.setVisible(false);
			searchBox.setFocus(true);
		}else{
			locationSearch.setVisible(false);
			locationSpecifics.setVisible(true);
			location_name.setFocus(true);
		}
	}

	public void setLocation(Location location)
	{
		this.location = location;
	}

	@UiHandler("button_find")
	public void onFindClick(ClickEvent e){
		location.setStreetAddress(searchBox.getText());
		Geocoder gCoder = new Geocoder();
		gCoder.getLocations(location.getStreetAddress(), new LocationCallback(){
			@Override
			public void onFailure(int statusCode) {
				String error = "An Unknown Error Occured";
				if(statusCode == StatusCodes.API_ERROR)
					error = "Error inside google api call";
				else if(statusCode == StatusCodes.BAD_KEY)
					error = "Bad Key Error. The given key is either invalid or " +
							"does not match the domain for which it was given.";
				else if(statusCode == StatusCodes.BAD_REQUEST)
					error = "Bad Request Error. A directions request could not be successfully parsed.";
				else if(statusCode == StatusCodes.MISSING_ADDRESS)
					error = "Missing Address Error. The HTTP q parameter was either missing or had no value.";
				else if(statusCode == StatusCodes.MISSING_QUERY){
					error = "No value entered in search box.";
					//error = "Missing Query Error. The HTTP q parameter was either missing or had no value."; 
				}
				else if(statusCode == StatusCodes.SERVER_ERROR)
					error = "Server Error.  A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.";
				else if(statusCode == StatusCodes.TOO_MANY_QUERIES)
					error = "Too Many Queries Error. The given key has gone over the requests limit in the 24 hour period.";
				else if(statusCode == StatusCodes.UNAVAILABLE_ADDRESS)
					error = "Unavailable Address Error. The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.";
				Window.alert(error);
			}
			@Override
			public void onSuccess(JsArray<Placemark> locations) {
				if(locations.length() < 1){
					Window.alert("No address found");
				} else if(locations.length() > 1){
					final MultipleAdressDialog dlg = new MultipleAdressDialog(locations);
					dlg.addCloseHandler(new CloseHandler<PopupPanel>(){
						@Override
						public void onClose(CloseEvent<PopupPanel> event) {
							Placemark selected = dlg.getSelected();
							if(selected != null)
								onAddressFound(selected);
						}

					});
					dlg.center();
				} else{
					Placemark location = locations.get(0);
					onAddressFound(location);

				}
			}
		});
	}

	@UiHandler("button_next")
	public void onButtonSave(ClickEvent e){
		String contactName = contact_name.getText();
//		if(contactName.length() == 0){
//			contact_name.addStyleName(TextBoxFormatError);
//			Window.alert("Your Name field cannot be empty");
//			return;
//		} else
//			contact_name.removeStyleName(TextBoxFormatError);
		String contactEmail = contact_email.getText();
//		RegExp regex_email = RegExp.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(?:[a-zA-Z]{2,6})$");
//		if(!regex_email.test(contactEmail)){
//			contact_email.addStyleName(TextBoxFormatError);
//			Window.alert("Email field must contain a valid email");
//			return;
//		} else
//			contact_email.removeStyleName(TextBoxFormatError);
		String contactPhone = contact_phone.getText();
//		RegExp regex_phone = RegExp.compile("^(?:(?:\\+?1\\s*(?:[.-]\\s*)?)?(?:\\(\\s" +
//				"*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\\s*\\)|([2-9]1[02-9" +
//				"]|[2-9][02-8]1|[2-9][02-8][02-9]))\\s*(?:[.-]\\s*)?)?([2-9]1[02-9]" +
//				"|[2-9][02-9]1|[2-9][02-9]{2})\\s*(?:[.-]\\s*)?([0-9]{4})(?:\\s*(?:" +
//				"#|x\\.?|ext\\.?|extension)\\s*(\\d+))?$");
//		if(!regex_phone.test(contactPhone)){
//			contact_phone.addStyleName(TextBoxFormatError);
//			Window.alert("Phone field must contain a valid phone number");
//			return;
//		} else
//			contact_phone.removeStyleName(TextBoxFormatError);
		String locationName = location_name.getText();
		if(locationName.length() == 0){
			location_name.addStyleName(TextBoxFormatError);
			Window.alert("Location Name field cannot be empty");
			return;
		} else
			location_name.removeStyleName(TextBoxFormatError);
		int food_type = foodType.getSelectedIndex();

		if(value == null)
			value = location;
		else{
			value.setCity(location.getCity());
			value.setState(location.getState());
			value.setZipCode(location.getZipCode());
		}

		value.setCreatorEmail(LoginInfoManager.getLoginInfo().getEmailAddress());

		value.setContactName(contactName);
		value.setContactEmail(contactEmail);
		value.setContactPhone(contactPhone);

		value.setName(locationName);
		value.setFoodTypeFromInt(new Long(food_type));
		value.setLatitude(googleMap.getMarker(value).getLatLng().getLatitude());
		value.setLongitude(googleMap.getMarker(value).getLatLng().getLongitude());
		value.setNotes(pickup_notes.getText());

		System.out.println(value);
		
		setValue(value);
	}

	@UiHandler("button_cancel_save")
	public void onButtonCancelSave(ClickEvent e){
		googleMap.removeMarker(location);
		setValue(null);
	}

	public void reset()
	{
		contact_name.setText("");
		contact_email.setText("");
		contact_phone.setText("");
		location_name.setText("");
		foodType.setSelectedIndex(0);
		pickup_notes.setText("");
	}

	@Override
	public HandlerRegistration addValueChangeHandler(
			ValueChangeHandler<Location> handler) {
		return addHandler(handler, ValueChangeEvent.getType());
	}

	@Override
	public Location getValue() {
		return value;
	}

	@Override
	public void setValue(Location value) {
		setValue(value, true);
	}

	@Override
	public void setValue(Location value, boolean fireEvents) {
		this.value = value;
		if(value == null){
			reset();
			location = new Location(type);
			locationSearch.setVisible(true);
			locationSpecifics.setVisible(false);
		}else{
			contact_name.setText(value.getContactName());
			contact_email.setText(value.getContactEmail());
			contact_phone.setText(value.getContactPhone());
			location_name.setText(value.getName());
			pickup_notes.setText(value.getNotes());
			foodType.setSelectedIndex(value.getFoodTypeAsInt());
			address_found_text1.setText(value.firstLineOfAddress());
			address_found_text2.setText(value.secondLineOfAddress());
			LatLng latlng = LatLng.newInstance(value.getLatitude(), value.getLongitude());
			googleMap.addMarker(value, latlng, false);
			switchMode(false);
		}
		if(fireEvents)
			ValueChangeEvent.fire(this, value);
	}
}
